分类
联系方式
  1. 新浪微博
  2. E-mail

Maxiee 的 Emacs 之旅:RSS 阅读器

介绍

Elfeed 是一个轻量且强大的 Emacs RSS 阅读器。有多强大呢?它能自动根据内容给 feed 打标签。除此之外,结合 elisp 和函数式编程,Elfeed 更像是一个 SDK,各个环节都可以进行定制,没有做不到,只有想不到。

为什么要在 Emacs 里使用 RSS 阅读器?

  1. Just for fun 😄
  2. 强大的二次开发能力
    1. 我的书签系统也是基于 org mode 可以打通
    2. 理想情况:需要 mark 的文章,直接 refile 到 bookmark 中
  3. 上班摸 🐟 不露痕迹 👀

二次开发能力值得一提,大多数产品都不具备开放性,开发者、产品经理设计成啥样就是啥样。但是,众口难调,每个人都有特殊的偏好。因此,只有开放性的产品才能满足对品质有要求的用户。如何提供开放性呢?有的产品提供 Plugin 插件机制,基于有限的 API 进行扩展。这种对 API 进行定制的能力,基于 OOP 语言是比较困难的。elisp + 函数式编程实现了完全定制能力,这是乐趣所在。

安装

我使用 Doom Emacs。Doom Emacs 中已经集成有 rss 模式。

进入 DOOMDIR/init.el 后,将 rss 对应项目解开注释即可。

(rss +org)

需要注意的是,+org 会同时安装 elfeed-org 这个扩展。elfeed 默认使用 elisp 管理 Feed,使用 elfeed-org 之后,改为使用 org 来管理 feed,更加方便。

关于 elfeed-org 的使用方式,会在后续小节中介绍。

本文后续的讲解也是基于 Doom Emacs,因为 Doom Emacs 对 elfeed 进行了二次定制,所以使用方式是与众不同的

进入 elfeed

M-x elfeed

内容为空,因为还没有添加 Feed。

数据库

Elfeed 采用数据库来存储 Feed 数据。神奇的是这个数据库也是 Plain Text 的,因此我能够使用 Git 跟踪。

通过下面代码,修改数据库路径:

;; 指定 elfeed 数据库所在目录
(setq elfeed-db-directory "~/org/elfeed")
;; 指定 elfeed-org feed 源声明对应文件
(setq rmh-elfeed-org-files (list "~/org/elfeed.org"))

使用 elfeed-org 管理订阅源

如果使用 elfeed-org,则使用 org 文件管理订阅源,对应文件为 ~/org/elfeed.org,具体内容:

其中:

  • 必须有一个跟节点,tag 必须为 elfeed,标题没要求
  • 内部标题随便订
    • 可以只插入一个 RSS Link
    • 也可以按照 Org Link 方式,给一个规整的名字
  • 标题可以插入 Tag,作为站点的 Tag 分类
    • Tag 是可以继承的,比如
      • 科技网站的 tag 是 tech
      • MakeTechEasier 会自动继承 tech 的 tag

刷新 Feed

回到 elfeed,执行 M-x elfeed-update。可以看到 Feed 拉取下来了:

打开资讯

两种打开方式:

  1. Enter 应用内打开
  2. Shift + Enter:通过浏览器打开

应用内打开效果:

按 q 后返回。

不论是应用内打开,还是浏览器打开,在资讯列表页,可看到该条目已置灰,表示已读。

添加 Tag

对于好文章,可以添加 Tag 归类:

  1. 首先移动到文章所在行
  2. 输入加号 +
  3. 底部会弹出 Tag 输入框,输入对应 Tag 名称即可

按 Tag 过滤

输入 s,底部出现一个 Filter 输入框。

输入框默认值包括 @2-week-ago,这是 Elfeed 中的过滤语法,只展示两周内的文章。

在其后添加 tag 名称即可:

  • +tag:表示正向条件,含该分类
  • -tag:表示负向条件,排除该分类
  • 不带加号:标题关键字搜索
  • 条件间通过空格间隔,同时生效

其中,可以看到,tag 是包含正反过滤的,非常方便。

举例来说,假设 mark 标签表示好文章,read 标签表示已读。那么 +mark -read 表示未读好文章。

按时间过滤

Elfeed 中包含了一个强大的标签系统,除了按标签过滤外,还支持按照时间进行过滤:

  • 最近六个月:@6-month-ago
  • 最近两周:@2-week-ago
  • 指定日期:@2020-06-19
  • 指定时间段:@2020-06-19--2020-03-10

自动刷新 Feed

Elfeed 并没有提供自动刷新机制,通过自定义,实现了两种方式。修改 doom emacs 的 config.el:

启动 elfeed 时拉取 feed

;; Automatically updating feed when opening elfeed
(add-hook! 'elfeed-search-mode-hook #'elfeed-update)

使用定时器

;; Run `elfeed-update' every 24 hours
(run-at-time nil (* 24 60 60) #'elfeed-update)

基于 URL 自动打标签

TBD:以下是 elfeed 原生方法,增加 elfeed-org 的方法。

elfeed-new-entry-hook 在添加条目时候的钩子方法。 在钩子中使用 elfeed-make-tagger 函数进行打标签。实例代码:

(add-hook 'elfeed-new-entry-hook
        (elfeed-make-tagger :feed-url "medium\\.com"
                            :add '(medium)))

这样,url 中带有 medium.com 的都会添加 medium 标签。 例2,只对 3 个月以前的文章打标签:

(add-hook 'elfeed-new-entry-hook
        (elfeed-make-tagger :feed-url "medium\\.com"
                            :before "3 months ago"
                            :add 'medium))

例3,自动对 youtube 网站打标签:

;; Mark all YouTube entries
(add-hook 'elfeed-new-entry-hook
          (elfeed-make-tagger :feed-url "youtube\\.com"
                              :add '(video youtube)))

例4,超过一定事前之前的,自动算作已读:

;; Entries older than 2 weeks are marked as read
(add-hook 'elfeed-new-entry-hook
          (elfeed-make-tagger :before "2 weeks ago"
                              :remove 'unread))

钩子函数

除了 elfeed-new-entry-hook 之外,还有以下钩子:

hook 功能
elfeed-new-entry-hook 添加新条目时调用
elfeed-new-entry-parse-hook 添加新条目解析内容时调用
elfeed-http-error-hooks 网络错误时调用
elfeed-parse-error-hooks 解析错误时调用
elfeed-db-update-hook 数据库主要修改更新时调用

展示条目

控制按下回车时的展示方式,通过 elfeed-show-mode 控制,默认是使用内置的 shr 包。

展示图片会导致 Emacs 变慢,可以设置 shr-inhibit-images 变量关闭图片展示。

elfeed-tube

除了订阅文章之外,通过 elfeed-tube 二次扩展,elfeed 还能够实现 Youtube 订阅。尤其地,还能与 youtube-dl 打通,实现视频下载。

网络资源

How to Use Emacs for RSS with Elfeed